<template>
  <div class="request-table-slot">
    <TableSlot v-loading="loading" class="table-slot" ref="refTableSlot" :data="list_data" :cols="cols" :has_select="has_select" :default_order="default_order" :row_class="row_class" :cell_class="cell_class"
               @change:selected="$emit('change:selected', $event)"
               @change:order="order=$event"
    >
      <template v-for="(slot, name) in $slots" v-slot:[name]="data">
        <slot :name="name" v-bind="data"></slot>
      </template>
    </TableSlot>
    <el-pagination v-if="limit" class="el-pagination" v-model:page-size="page_size" v-model:current-page="page"
                   :total="page_count || 0" :page-sizes="[20, 50, 100, 300]" :background="false" layout="total, sizes, prev, pager, next, jumper" >
    </el-pagination>
  </div>
</template>

<script setup lang="ts">
// @ts-nocheck
import TableSlot, {type TypeCol} from "@/components/slot/TableSlot.vue";
import {onMounted, type PropType, type Ref, ref, watch} from "vue";
import {debounce} from "@/js/s94_tool";
import {ajax} from "@/js/api_tool";

defineOptions({
  _title_: '请求表格',
  _tip_: '请求接口，以响应的data.list数据作列表数据渲染表格，包括了翻页功能（如果设定了page_size）',
  _css_var_: {},
  components: {TableSlot},
})

const props = defineProps({
  cols: {
    type: Object as PropType<{[name:string]: TypeCol}>,
    default: {},
  },
  default_order: {
    type: String,
    default: '',
  },
  has_select: {
    type: Boolean,
    default: true,
  },
  row_class: {
    type: [String, Function] as PropType<string | ((data: { row: any, rowIndex: number }) => string)>,
  },
  cell_class: {
    type: [String, Function]  as PropType<string | ((data: { row: any, column: any, rowIndex: number, columnIndex: number }) => string)>,
  },
  // --------- 以上为透传的 TableSlot 参数 ----------
  url: {
    type: String,
    required: true,
  },
  request_data: {
    type: Object,
    default: {},
  },
  list_handle: {
    type: Function as PropType<(list:any[])=>any[]>,
    default: (list:any[])=>list
  },
  limit: {
    type: [String, Number],
  },
  default_page: {
    type: [String, Number],
    default: 1,
    _tip_: '默认的的页码'
  },
  load_before: {
    type: Function as PropType<(form_data:{[name:string]: any})=>boolean|Promise<boolean>>,
    default: (form_data)=>true
  },
  load_after: {
    type: Function as PropType<(res:any)=>any>,
    default: (val:any)=>val
  },
  p_start_1: Boolean,
})
const emit = defineEmits(['change:selected', 'loaded'])

const list_data:Ref<any[]> = ref([])
const loading = ref(false)
const page_size = ref(Number(props.limit) || 20)
const page_count:Ref<undefined|number> = ref(undefined)
const page = ref(Number(props.default_page) || 1)
const order = ref(props.default_order)

const load = debounce(async function(){
  if (!props.url) return console.error('请求地址不存在');
  const url = props.url;
  const page_this = page.value;
  let data = {...props.request_data}
  if (props.limit) {
    data.p = page.value - (props.p_start_1?0:1);
    data.n = page_size.value;
  }
  const need_count = typeof page_count.value === 'undefined';
  if (need_count){
    data._need_count_ = 1;
  }
  if(order.value) {
    let [name, ac=''] = order.value.split(' ');
    data.order = Object.assign(data.order||{}, {[name]: ac})
  }
  let res_load_before = await props.load_before(data);
  if (res_load_before===false) return console.log('【RequestTableSlot】load_before 回调方法返回 false ，中止了请求');
  if (loading.value) return;
  loading.value = true;
  let res = await ajax({url, data});
  if (need_count){
    page_count.value = Number(res?.data?.count) || 0;
  }
  emit('loaded', res);
  res = props.load_after(res);
  if (page_this !== page.value) return console.log(`【RequestTableSlot】页码不匹配（${page_this}<>${page.value}），舍弃本次响应数据`); // 页码不匹配，直接返回，舍弃本次响应数据
  list_data.value = props.list_handle(res?.data?.list || []);
  loading.value = false;
}, 100)
function load_init(){
  list_data.value = [];
  page.value = 1;
  page_count.value = undefined;
  loading.value = false;
  load();
}

watch(()=>props.url, function (){
  load_init();
})
watch(()=>props.request_data, function (v, oldV){
  if (JSON.stringify(v) !== JSON.stringify(oldV)) load_init();
})
watch(()=>props.default_page, function (v){
  let default_page = Number(v);
  if (default_page > 0) page.value = default_page;
})
watch(()=>props.default_order, function (v){
  if (v !== order.value){
    order.value = order;
  }
})
watch(order, function (v, oldV){
  load();
})
watch(page, function (v, oldV){
  load();
})
watch(page_size, function (v, oldV){
  load();
})

onMounted(()=>{
  load();
})

</script>
<style scoped>
.request-table-slot{display: flex;flex-direction: column;overflow: hidden;}
.request-table-slot>*{width: 100%;}
.table-slot{flex-grow: 1;flex-shrink: 1;}
.el-pagination{flex-grow: 0;flex-shrink: 0;padding: 10px;width: 100%;}
</style>
